package spinning

import (
	"encoding/json"
	"fmt"
	"time"

	mqtt "github.com/eclipse/paho.mqtt.golang"
	_ "github.com/mattn/go-sqlite3"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"

	"github.com/edgexfoundry/app-functions-sdk-go/v2/pkg/interfaces"
	"github.com/edgexfoundry/app-functions-sdk-go/v2/pkg/util"
)

func (app *SpinningApp) handleMcuRealtimeMsg(appContext interfaces.AppFunctionContext, data interface{}) (bool, interface{}) {
	// 处理 从 MCU 发送来的消息
	fmt.Println("### edgex/event/mcu/realtime begin ###")
	input, err := util.CoerceType(data)

	if err != nil {
		appContext.LoggingClient().Error(err.Error())
		return false, err
	}

	// 机台状态 转换成 纺纱周期、停车记录
	// 将MCU发送来的数据 保存到 全局变量中：realtimeInfo
	var mcuRealtime = McuRealtime{} // 临时接收 机台 实时产量 数据
	err2 := json.Unmarshal(input, &mcuRealtime)
	if err2 != nil {
		panic(err2)
	}

	// status 有效值范围： 1,2,0
	if mcuRealtime.Status != 1 && mcuRealtime.Status != 2 && mcuRealtime.Status != 0 {
		return false, nil
	}

	mcu_output_db, err3 := gorm.Open(sqlite.Open("../db/realtime.db3"), &gorm.Config{})
	if err3 != nil {
		appContext.LoggingClient().Info(err3.Error())
	}

	appContext.LoggingClient().Info("handleMcuRealtimeMsg")

	// 保存到本地 数据库
	mcu_output_db.Create(&mcuRealtime)

	appContext.SetResponseData([]byte("success"))

	// 机台状态发生变化， 则要做
	point := time.Now().Unix() / 5
	if app.mcuRealtime.Status == mcuRealtime.Status {

		if point == 0 {
			app.mcuRealtime.copy_from(&mcuRealtime)
		}
		return false, nil
	}

	// 落纱停车结束，新的纺纱周期开始
	if mcuRealtime.Status == 1 && app.mcuRealtime.Status == 0 {
		app.process_status_1_0(&mcuRealtime)
		// 重新初始化
		app.doffing.init(mcuRealtime.Ts)
	}

	// 中途停车结束
	if mcuRealtime.Status == 1 && app.mcuRealtime.Status == 2 {
		app.process_status_1_2(&mcuRealtime)
	}

	// 中途停车结束
	if mcuRealtime.Status == 0 && app.mcuRealtime.Status == 1 {
		app.process_status_0_1(&mcuRealtime)
	}

	// 中途停车结束
	if mcuRealtime.Status == 2 && app.mcuRealtime.Status == 1 {
		app.process_status_2_1(&mcuRealtime)
	}

	// 中途停车结束
	if mcuRealtime.Status == 2 && app.mcuRealtime.Status == 0 {
		app.process_status_2_0(&mcuRealtime)
	}

	// 把最新值复制到 全局变量中
	app.mcuRealtime.copy_from(&mcuRealtime)

	fmt.Println("### edgex/event/mcu/realtime end ###")
	return false, nil
}

func (app *SpinningApp) handleMqttRealtimeMsg(client mqtt.Client, message mqtt.Message) {
	// 处理 从 MCU 发送来的消息
	fmt.Println("### edgex/event/mcu/realtime begin ###")

	// 机台状态 转换成 纺纱周期、停车记录
	// 将MCU发送来的数据 保存到 全局变量中：realtimeInfo
	var mcuRealtime = McuRealtime{} // 临时接收 机台 实时产量 数据
	err2 := json.Unmarshal(message.Payload(), &mcuRealtime)
	if err2 != nil {
		panic(err2)
	}

	// status 有效值范围： 1,2,0
	if mcuRealtime.Status != 1 && mcuRealtime.Status != 2 && mcuRealtime.Status != 0 {
		return
	}

	mcu_output_db, err3 := gorm.Open(sqlite.Open("../db/realtime.db3"), &gorm.Config{})
	if err3 != nil {
		fmt.Println(err3.Error())
	}

	fmt.Println("handleMcuRealtimeMsg")

	// 保存到本地 数据库
	mcu_output_db.Create(&mcuRealtime)

	// 机台状态发生变化， 则要做
	point := time.Now().Unix() / 5
	if app.mcuRealtime.Status == mcuRealtime.Status {

		if point == 0 {
			app.mcuRealtime.copy_from(&mcuRealtime)
		}
		return
	}

	// 落纱停车结束，新的纺纱周期开始
	if mcuRealtime.Status == 1 && app.mcuRealtime.Status == 0 {
		app.process_status_1_0(&mcuRealtime)
		// 重新初始化
		app.doffing.init(mcuRealtime.Ts)
	}

	// 中途停车结束
	if mcuRealtime.Status == 1 && app.mcuRealtime.Status == 2 {
		app.process_status_1_2(&mcuRealtime)
	}

	// 中途停车结束
	if mcuRealtime.Status == 0 && app.mcuRealtime.Status == 1 {
		app.process_status_0_1(&mcuRealtime)
	}

	// 中途停车结束
	if mcuRealtime.Status == 2 && app.mcuRealtime.Status == 1 {
		app.process_status_2_1(&mcuRealtime)
	}

	// 中途停车结束
	if mcuRealtime.Status == 2 && app.mcuRealtime.Status == 0 {
		app.process_status_2_0(&mcuRealtime)
	}

	// 把最新值复制到 全局变量中
	app.mcuRealtime.copy_from(&mcuRealtime)

	fmt.Println("### edgex/event/mcu/realtime end ###")
}

func (app *SpinningApp) process_status_1_0(mcuRealtime *McuRealtime) {
	// 处理机台状态 从 1 到 0, 纺纱周期结束

	// 1 关闭当前纺纱周期， 并更新到 数据中
	app.doffing.End = mcuRealtime.Ts
	app.doffing.Spin_len = mcuRealtime.Spin_len
	app.doffing.Actual_len = mcuRealtime.Actual_len
	app.doffing.theory_total0 = mcuRealtime.Theory_len
	app.doffing.actual_total0 = mcuRealtime.Actual_len
	app.doffing.Progress = mcuRealtime.Progress
	app.doffing.Efficiency = mcuRealtime.Efficiency
	app.doffing.Brokens = mcuRealtime.Brokens
	app.doffing.Noocupations = mcuRealtime.Noocupations
	app.doffing.Weaks = mcuRealtime.Weaks
	app.doffing.Malfunctions = mcuRealtime.Malfunctions
	app.doffing.Passbys = mcuRealtime.Passbys
	// TO-DO 计算其他统计参数

	doffing_db, err := gorm.Open(sqlite.Open("../db/doffing.db3"), &gorm.Config{})
	if err != nil {
		fmt.Println(err.Error())
	}

	var doff = Doffing{}

	// 2 当前纺纱周期 更新到 数据库中
	doffing_db.Where("id = ?", app.doffing.ID).Find(&doff).Updates(&app.doffing)
	doffing_db.Commit()

	// 3 创建停车记录
	app.stop.ID = 0
	app.stop.Begin = mcuRealtime.Ts
	app.stop.Status = 0

	stop_db, err := gorm.Open(sqlite.Open("../db/stop.db3"), &gorm.Config{})
	stop_db.Create(&app.stop)
}

func (app *SpinningApp) process_status_1_2(mcuRealtime *McuRealtime) {

}

func (app *SpinningApp) process_status_0_1(mcuRealtime *McuRealtime) {

}

func (app *SpinningApp) process_status_2_1(mcuRealtime *McuRealtime) {

}

func (app *SpinningApp) process_status_2_0(mcuRealtime *McuRealtime) {

}
